// CommandInterface.cpp
//
// Copyright (c) 2008 Bojan Rajkovic
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//

#include "../include/CommandInterface.h"

void CommandInterface::Run() {
	
	Utility::LogMessage(_("Started command interface."), M_INFO);
	commandSocket = new UNIXListenerSocket();
	// Well, it should be set up now. The default constructor calls Open() with the default location
	
	while (1) {
		Utility::LogMessage(_("Waiting for a connection on control socket"), M_INFO);	
		commandSocket->Accept();
		Utility::LogMessage(_("Client connected to control socket."), M_INFO);
			
		int done = 0;
			
		while (!done) {
			
			// Just read a line
			std::string receiveBuffer = commandSocket->ReadLine();
			
			if (receiveBuffer.size() == 0) {
				// Ditch out of the loop, go back to waiting for accept().
				break;
			}
			
			// Sanitize our input
			Utility::SanitizeString(receiveBuffer);
			
			// now we gotta handle the commands that come in
			// they're in the format "get something" or "send something"
			// for send something the only possibility right now is pulse
			// for get, it can be keys, session_keys, uptime_average, runtime_average, last_pulse
			std::string command, arg, response;
			
			std::vector<std::string> splitVector;
			
			boost::algorithm::split(splitVector, receiveBuffer, boost::algorithm::is_any_of(" "));
			
			if (splitVector.size() == 2) {
				command = splitVector[0];
				arg = splitVector[1];
			} else {
				commandSocket->Write(_("Either command, argument or both are missing, or you've got extras."
					"please check your input.\n"));
				continue;
			}
			
			#ifdef DEBUG
			Utility::LogMessage(Utility::FormatString(_("Received %s on command interface, parses to command %s with "
				"argument %s."), receiveBuffer.c_str(), command.c_str(), arg.c_str()), M_INFO);
			#endif
					
			if (command == "get") {
				if (strcmp(arg.c_str(),"keys") == 0) {
					response = Utility::FormatString("%lu", this->keycounter->Keys());
				} else if (strcmp(arg.c_str(), "sessionKeys") == 0) {
					response = Utility::FormatString("%lu", this->keycounter->SessionKeys());
				} else if (strcmp(arg.c_str(), "uptimeAverage") == 0) {
					response = Utility::FormatString("%f", 
						this->keycounter->SessionKeys()/this->keycounter->SystemUptime());
				} else if (strcmp(arg.c_str(), "runtimeAverage") == 0) {
					response = Utility::FormatString("%f", 
						this->keycounter->SessionKeys()/this->keycounter->ProgramUptime());
				} else if (strcmp(arg.c_str(), "lastPulse") == 0) {
					response = Utility::FormatString("%f", 
						this->keycounter->TimeSinceLastPulse());
				} else {
					response = Utility::FormatString(_("Invalid argument %s to get"), arg.c_str());
				}
			} else if (command == "send") {
				if (strcmp(arg.c_str(), "pulse") == 0) {
					if (this->keycounter->Pulse()) {
						response = Utility::FormatString(_("Pulse successful."));
					} else {
						response = Utility::FormatString(_("Pulse failed."));
						break;
					}
				} else {
					response = Utility::FormatString(_("Invalid argument %s to send"), arg.c_str());
				}
			} else if (command == "do") {
				if (strcmp(arg.c_str(), "term") == 0) {
					response = Utility::FormatString(_("Starting to terminate, sending SIGINT to parent pid %d"),
						getpid());
					commandSocket->Write(response);
					Utility::LogMessage(_("Told to die on command interface, going down with SIGINT."), M_INFO);
					kill(getpid(), SIGINT);
					return;
				} else {
					response = Utility::FormatString(_("Invalid argument %s to do"), arg.c_str());
				}
			} else {
				response = Utility::FormatString(_("Invalid command %s"), command.c_str());
			}

			if (!done) {
				commandSocket->WriteLine(response);
			}

		}	

		Utility::LogMessage(_("Client disconnected from control socket."), M_INFO);
		commandSocket->CloseRemoteSocket();
	}			
}
